<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Generator 函数 | 20秒的勇气</title>
    <meta name="generator" content="VuePress 1.5.3">
    <script>var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?01611e9c2d4c65531fe791d0a83e6ebd";
        var s = document.getElementsByTagName("script")[0]; 
        s.parentNode.insertBefore(hm, s);
      })()</script>
    <meta name="description" content="欢迎来到wenbintian的博客">
    <link rel="preload" href="/blog/assets/css/0.styles.5dc057b1.css" as="style"><link rel="preload" href="/blog/assets/js/app.2a047d56.js" as="script"><link rel="preload" href="/blog/assets/js/2.cc145974.js" as="script"><link rel="preload" href="/blog/assets/js/16.2e8857c5.js" as="script"><link rel="prefetch" href="/blog/assets/js/10.dc9f6a74.js"><link rel="prefetch" href="/blog/assets/js/11.f7ecaf96.js"><link rel="prefetch" href="/blog/assets/js/12.4363725a.js"><link rel="prefetch" href="/blog/assets/js/13.0fd4b251.js"><link rel="prefetch" href="/blog/assets/js/14.edc7bd5f.js"><link rel="prefetch" href="/blog/assets/js/15.647c0964.js"><link rel="prefetch" href="/blog/assets/js/17.1c7cc9ee.js"><link rel="prefetch" href="/blog/assets/js/18.bf88a22d.js"><link rel="prefetch" href="/blog/assets/js/19.1433c5a8.js"><link rel="prefetch" href="/blog/assets/js/20.713720d3.js"><link rel="prefetch" href="/blog/assets/js/21.51a3d47b.js"><link rel="prefetch" href="/blog/assets/js/22.04488762.js"><link rel="prefetch" href="/blog/assets/js/23.b9337410.js"><link rel="prefetch" href="/blog/assets/js/24.d0d5b562.js"><link rel="prefetch" href="/blog/assets/js/25.e76a54ef.js"><link rel="prefetch" href="/blog/assets/js/26.006d0afa.js"><link rel="prefetch" href="/blog/assets/js/27.38ec3468.js"><link rel="prefetch" href="/blog/assets/js/28.c8cf7077.js"><link rel="prefetch" href="/blog/assets/js/29.70f03487.js"><link rel="prefetch" href="/blog/assets/js/3.9bfe5560.js"><link rel="prefetch" href="/blog/assets/js/30.3e6d6ba9.js"><link rel="prefetch" href="/blog/assets/js/31.1dbd85cb.js"><link rel="prefetch" href="/blog/assets/js/32.208e4272.js"><link rel="prefetch" href="/blog/assets/js/33.979228dd.js"><link rel="prefetch" href="/blog/assets/js/34.6ad6fae2.js"><link rel="prefetch" href="/blog/assets/js/35.59b3e591.js"><link rel="prefetch" href="/blog/assets/js/36.7239d917.js"><link rel="prefetch" href="/blog/assets/js/37.a8305f70.js"><link rel="prefetch" href="/blog/assets/js/38.7e3197cd.js"><link rel="prefetch" href="/blog/assets/js/39.1bb3ad3b.js"><link rel="prefetch" href="/blog/assets/js/4.3b6a7e49.js"><link rel="prefetch" href="/blog/assets/js/40.bc263e99.js"><link rel="prefetch" href="/blog/assets/js/41.4ee25f6a.js"><link rel="prefetch" href="/blog/assets/js/42.37c6cc26.js"><link rel="prefetch" href="/blog/assets/js/43.9a40d780.js"><link rel="prefetch" href="/blog/assets/js/44.2eda0bb6.js"><link rel="prefetch" href="/blog/assets/js/45.ce3372d9.js"><link rel="prefetch" href="/blog/assets/js/46.17e44796.js"><link rel="prefetch" href="/blog/assets/js/47.f845ed6d.js"><link rel="prefetch" href="/blog/assets/js/5.bc6e1aa4.js"><link rel="prefetch" href="/blog/assets/js/6.e0f80af7.js"><link rel="prefetch" href="/blog/assets/js/7.c808e2d2.js"><link rel="prefetch" href="/blog/assets/js/8.902b76dc.js"><link rel="prefetch" href="/blog/assets/js/9.9bb8a7fe.js">
    <link rel="stylesheet" href="/blog/assets/css/0.styles.5dc057b1.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/blog/" class="home-link router-link-active"><!----> <span class="site-name">20秒的勇气</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/blog/knowledge/" class="nav-link router-link-active">
  知识篇
</a></div><div class="nav-item"><a href="/blog/notes/" class="nav-link">
  随身笔记
</a></div> <a href="https://github.com/wenbintian" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/blog/knowledge/" class="nav-link router-link-active">
  知识篇
</a></div><div class="nav-item"><a href="/blog/notes/" class="nav-link">
  随身笔记
</a></div> <a href="https://github.com/wenbintian" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><a href="/blog/knowledge/book/" class="sidebar-heading clickable"><span>读书篇</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/blog/knowledge/tool/" class="sidebar-heading clickable"><span>工具篇</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/blog/knowledge/css/" class="sidebar-heading clickable"><span>CSS篇</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/blog/knowledge/js/" class="sidebar-heading clickable router-link-active open"><span>JS篇</span> <span class="arrow down"></span></a> <ul class="sidebar-links sidebar-group-items"><li><section class="sidebar-group collapsable is-sub-group depth-1"><a href="/blog/knowledge/js/es6/" class="sidebar-heading clickable router-link-active open"><span>ES6</span> <span class="arrow down"></span></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/knowledge/js/es6/promise.html" class="sidebar-link">Promise 对象</a></li><li><a href="/blog/knowledge/js/es6/generator.html" aria-current="page" class="active sidebar-link">Generator 函数</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#简介" class="sidebar-link">简介</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#yield-表达式" class="sidebar-link">yield 表达式</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#与-iterator-接口的关系" class="sidebar-link">与 Iterator 接口的关系</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#next-方法的参数" class="sidebar-link">next 方法的参数</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#for-of循环" class="sidebar-link">for...of循环</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#generator-prototype-throw-抛出错误" class="sidebar-link">Generator.prototype.throw() 抛出错误</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#generator-prototype-return" class="sidebar-link">Generator.prototype.return()</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#yield-表达式-2" class="sidebar-link">yield* 表达式</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#generator-函数的this" class="sidebar-link">Generator 函数的this</a></li><li class="sidebar-sub-header"><a href="/blog/knowledge/js/es6/generator.html#async函数" class="sidebar-link">async函数</a></li></ul></li><li><a href="/blog/knowledge/js/es6/proxy.html" class="sidebar-link">Proxy 对象</a></li><li><a href="/blog/knowledge/js/es6/reflect.html" class="sidebar-link">Reflect 对象</a></li><li><a href="/blog/knowledge/js/es6/iterator.html" class="sidebar-link">Iterator(遍历器)</a></li><li><a href="/blog/knowledge/js/es6/map.html" class="sidebar-link">Map 对象</a></li></ul></section></li><li><section class="sidebar-group collapsable is-sub-group depth-1"><a href="/blog/knowledge/js/vue/" class="sidebar-heading clickable"><span>VUE</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable is-sub-group depth-1"><a href="/blog/knowledge/js/other/" class="sidebar-heading clickable"><span>其他</span> <span class="arrow right"></span></a> <!----></section></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="generator-函数"><a href="#generator-函数" class="header-anchor">#</a> Generator 函数</h1> <h2 id="简介"><a href="#简介" class="header-anchor">#</a> 简介</h2> <ul><li><code>Generator</code> 函数是 ES6 提供的一种异步编程解决方案。</li> <li>语法上， <code>Generator</code>函数是一个状态机，封装了多个内部状态。</li> <li>执行 <code>Generator</code>函数会返回一个遍历器对象，即<code>Generator</code>函数既是状态机，也是一个遍历器对象生成函数。</li> <li>形式上， <code>Generator</code>是一个普通函数，但有两个特征。一是， <code>function</code>关键字与函数名之间有一个星号；二是，函数体内部使用<code>yield</code>表达式（意思“产出”）。</li></ul> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">helloGenerator</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">yield</span> <span class="token string">'hello'</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token string">'world'</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token string">'end'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> hg <span class="token operator">=</span> <span class="token function">helloGenerator</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><ul><li>调用<code>Generator</code>函数后，函数并不会执行，而只是返回一个指向内部状态的指针对象，即遍历器对象。</li></ul> <div class="language-javascript extra-class"><pre class="language-javascript"><code>hg<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// { value: 'hello', done: false }</span>

hg<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// { value: 'world', done: false }</span>

hg<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// { value: 'end', done: false }</span>

hg<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// { value: undefined, done: false }</span>
</code></pre></div><ul><li>调用<code>next</code>方法，使得指针移向下一个状态，而<code>yield</code>表达式是暂停执行的标记。</li></ul> <h2 id="yield-表达式"><a href="#yield-表达式" class="header-anchor">#</a> yield 表达式</h2> <ul><li><code>yield</code>表达式后面的值作为返回对象的<code>value</code>的值。</li> <li>遇到<code>return</code>,则其后面的值作为返回对象的<code>value</code>的值，之后再调用<code>next</code>则就是<code>undefined</code>。</li></ul> <h2 id="与-iterator-接口的关系"><a href="#与-iterator-接口的关系" class="header-anchor">#</a> 与 Iterator 接口的关系</h2> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// to do something</span>
<span class="token punctuation">}</span>

<span class="token keyword">var</span> g <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

g<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> g
<span class="token comment">// true</span>
</code></pre></div><ul><li>上面代码中， <code>gen</code>是一个<code>Generator</code>函数，调用它会生成一个遍历器对象<code>g</code>。它的<code>Symbol.iterator</code>属性，也是一个遍历器对象生成器，执行它会返回它自己（遍历器对象<code>g</code>）。</li></ul> <h2 id="next-方法的参数"><a href="#next-方法的参数" class="header-anchor">#</a> next 方法的参数</h2> <ul><li><code>yield</code>表达式本身没有返回值，<code>next</code>可带一参数，当作上一个<code>yield</code>的返回值。</li></ul> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">var</span> r <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token number">2</span>
  <span class="token keyword">var</span> t <span class="token operator">=</span> r <span class="token operator">*</span> <span class="token number">3</span>
  <span class="token keyword">return</span> t
<span class="token punctuation">}</span>

<span class="token keyword">var</span> g <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// { value: 2, done: false }</span>
g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span>
<span class="token comment">// { value: 9, done: true }</span>
</code></pre></div><h2 id="for-of循环"><a href="#for-of循环" class="header-anchor">#</a> for...of循环</h2> <ul><li>return 语句的值并不会被遍历出来。同时 扩展运算符(...)、结构赋值和<code>Array.from</code>方法内部调用的，都是遍历器接口。如下</li></ul> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">numbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">yield</span> <span class="token number">1</span>
  <span class="token keyword">yield</span> <span class="token number">2</span>
  <span class="token keyword">yield</span> <span class="token number">3</span>
  <span class="token keyword">return</span> <span class="token number">4</span>
<span class="token punctuation">}</span>

<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> key <span class="token keyword">of</span> <span class="token function">numbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">// 1 2 3</span>

<span class="token punctuation">[</span><span class="token operator">...</span>numbers<span class="token punctuation">]</span>
<span class="token comment">// [1, 2, 3]</span>

<span class="token keyword">let</span> <span class="token punctuation">[</span>x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> z<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">numbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// x: 1</span>
<span class="token comment">// y: 2</span>
<span class="token comment">// z: 3</span>

Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token function">numbers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// [1, 2, 3]</span>

</code></pre></div><h2 id="generator-prototype-throw-抛出错误"><a href="#generator-prototype-throw-抛出错误" class="header-anchor">#</a> Generator.prototype.throw() 抛出错误</h2> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">var</span> <span class="token function-variable function">gen</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
  <span class="token keyword">try</span> <span class="token punctuation">{</span>
    <span class="token keyword">yield</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// ...</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">yield</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'c'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">var</span> g <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// a</span>
g<span class="token punctuation">.</span><span class="token function">throw</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// b</span>
g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// c</span>
</code></pre></div><ul><li>首先必须先执行一次<code>next</code>，之后抛错才能被内部捕获，因为第一次执行<code>next</code>等同于启动执行<code>Generator</code>函数的内部代码。</li> <li><code>g.throw()</code>执行后悔附带执行一条<code>yield</code>表达式</li> <li><code>g.throw()</code>执行若内部没有去<code>try..catch</code>捕获，那么它将会把错误信息抛到函数外。</li> <li><code>g.throw(e)</code>可以带一参数，该参数会在<code>try...catch</code>那被传出。</li></ul> <h2 id="generator-prototype-return"><a href="#generator-prototype-return" class="header-anchor">#</a> Generator.prototype.return()</h2> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">yield</span> <span class="token number">1</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token number">2</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">var</span> g <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// { value: 1, done: false }</span>
g<span class="token punctuation">.</span><span class="token function">return</span><span class="token punctuation">(</span><span class="token string">'foo'</span><span class="token punctuation">)</span>
<span class="token comment">// { value: 'foo', done: false }</span>
g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// { value: undefined, done: false }</span>
</code></pre></div><ul><li><code>return</code>方法，可以返回指定的值，并终结遍历器<code>Generator</code>函数，之后调用<code>next</code>方法的value值都返回<code>undefined</code>。</li></ul> <h2 id="yield-表达式-2"><a href="#yield-表达式-2" class="header-anchor">#</a> yield* 表达式</h2> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">bar</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">yield</span> <span class="token string">'x'</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span><span class="token operator">*</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token string">'y'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 等同于</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">bar</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">yield</span> <span class="token string">'x'</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token string">'a'</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token string">'b'</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token string">'y'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 等同于</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">bar</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">yield</span> <span class="token string">'x'</span><span class="token punctuation">;</span>
  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> v <span class="token keyword">of</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">yield</span> v<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">yield</span> <span class="token string">'y'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> v <span class="token keyword">of</span> <span class="token function">bar</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// &quot;x&quot;</span>
<span class="token comment">// &quot;a&quot;</span>
<span class="token comment">// &quot;b&quot;</span>
<span class="token comment">// &quot;y&quot;</span>
</code></pre></div><h2 id="generator-函数的this"><a href="#generator-函数的this" class="header-anchor">#</a> Generator 函数的this</h2> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">g</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

g<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">hello</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token string">'hi!'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token function">g</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

obj <span class="token keyword">instanceof</span> <span class="token class-name">g</span> <span class="token comment">// true</span>
obj<span class="token punctuation">.</span><span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 'hi!'</span>
</code></pre></div><ul><li><code>Generator</code>函数<code>g</code>返回的遍历器<code>obj</code>，是<code>g</code>的实例，而且继承了<code>g.prototype</code>.</li></ul> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">g</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>a <span class="token operator">=</span> <span class="token number">11</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token function">g</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
obj<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
obj<span class="token punctuation">.</span>a <span class="token comment">// undefined</span>
</code></pre></div><ul><li><code>Generator</code>函数<code>g</code>在<code>this</code>对象上面添加了一个属性<code>a</code>，但是<code>obj</code>对象拿不到这个属性。</li> <li><code>Generator</code>函数也不能跟<code>new</code>一起使用。</li></ul> <h2 id="async函数"><a href="#async函数" class="header-anchor">#</a> async函数</h2> <ul><li>是<code>Generator</code>函数的语法糖，<code>async</code>相当于<code>*</code>,<code>await</code>相当于<code>yield</code>。</li> <li>（1）<code>async</code>函数自带执行器，跟普通函数一模一样，不像<code>generator</code>需要调用<code>next</code>方法。</li> <li>（2） 语义更加清楚，<code>async</code>表示函数里有异步操作，<code>await</code>表示等待后面的表达式的结果</li> <li>（3）<code>await</code>后面可以是<code>Promise</code>对象或者原始类型的值，但此时都会转成立即执行<code>resolved</code>的<code>Promise</code>对象。</li> <li>（4）返回<code>Promise</code>对象，用<code>then</code>指定下一步操作。</li></ul></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">最后一次修改时间:</span> <span class="time">9/28/2020, 11:37:23 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/blog/knowledge/js/es6/promise.html" class="prev">
        Promise 对象
      </a></span> <span class="next"><a href="/blog/knowledge/js/es6/proxy.html">
        Proxy 对象
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/blog/assets/js/app.2a047d56.js" defer></script><script src="/blog/assets/js/2.cc145974.js" defer></script><script src="/blog/assets/js/16.2e8857c5.js" defer></script>
  </body>
</html>
